package com.jwsoft.manager.core.integration.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.IdcardUtil;
import com.bifang.engine.assistant.core.annotation.ApiService;
import com.bifang.engine.assistant.core.annotation.OpApi;
import com.bifang.engine.assistant.core.annotation.SaveOplog;
import com.bifang.engine.assistant.core.enums.AuTypeEnum;
import com.bifang.engine.assistant.core.enums.FuncTypeEnum;
import com.bifang.engine.data.core.util.PagerUtil;
import com.jwsoft.manager.common.enums.CardTypeEnum;
import com.jwsoft.manager.core.util.EduHelper;
import org.apache.commons.lang3.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.convert.Convert;
import cn.hutool.extra.servlet.ServletUtil;
import java.util.*;

import org.springframework.web.multipart.MultipartFile;
import com.bifang.engine.assistant.core.exception.AppException;
import org.springframework.util.ObjectUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStream;
import java.io.File;
import java.io.BufferedInputStream;
import javax.servlet.http.HttpServletResponse;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bifang.module.base.common.vo.dict.SelectVO;
import com.bifang.module.base.core.helper.DictHelper;
import com.bifang.module.system.core.util.AreaCodeHelper;
import com.bifang.module.base.core.utils.CommonUtil;
import com.bifang.module.base.common.vo.excel.ExcelModelVO;
import com.bifang.module.base.common.vo.excel.ExcelVO;
import com.bifang.module.base.core.helper.ExcelCommonHelper;
import com.bifang.module.base.core.integration.ExcelIntegration;
import com.jwsoft.manager.common.enums.EduTalentPoolDictEnum;
import com.jwsoft.manager.common.vo.eduTalentPool.eduTalentPool.EduTalentPoolVO;
import com.jwsoft.manager.common.vo.eduTalentPool.eduTalentPool.EduTalentPoolKeyVO;
import com.jwsoft.manager.common.vo.eduTalentPool.eduTalentPool.EduTalentPoolQueryVO;
import com.jwsoft.manager.common.vo.eduTalentPool.eduTalentPool.EduTalentPoolImpFileVO;
import com.jwsoft.manager.core.integration.EduTalentPoolIntegration;
import com.jwsoft.manager.core.dao.service.EduTalentPoolService;
import com.jwsoft.manager.core.dao.model.EduTalentPool;
/**
* 人才库信息 业务实现类
*
* @author chenzh 845078693@qq.com
* @since 1.0.0 2025-05-07
*/
@ApiService(funcCode = "eduTalentPool", title = "人才库信息")
@Slf4j
public class EduTalentPoolIntegrationImpl implements EduTalentPoolIntegration {

    @Autowired
    private EduTalentPoolService eduTalentPoolService;
    @Autowired
    private DictHelper dictHelper;
    @Autowired
    private AreaCodeHelper areaCodeHelper;
    @Autowired
    private ExcelIntegration excelIntegration;
    @Autowired
    private ExcelCommonHelper excelCommonHelper;
    @Autowired
    private EduHelper eduHelper;
    @Autowired
    private PlatformTransactionManager transactionManager;
    @Value("${spring.servlet.multipart.location}")
    private String tempPath;
    @Override
    @OpApi(funcCode = "eduTalentPool0001", title = "人才库信息分页查询", funcType = FuncTypeEnum.query,checkPrivilege = BoolEnum.FALSE)
    public PageInfo<EduTalentPoolVO> getList(EduTalentPoolQueryVO vo) {
        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(100);
        }

        List<String> areaCodeList=areaCodeHelper.getAreaCodeList(vo.getAreaCode());
        if (CollectionUtils.isEmpty(areaCodeList)){
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        vo.setAreaCodeList(areaCodeList);
        QueryWrapper<EduTalentPool> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(!CollectionUtils.isEmpty(vo.getAreaCodeList()), EduTalentPool::getAreaCode, vo.getAreaCodeList());
        queryWrapper.lambda().eq(!ObjectUtils.isEmpty(vo.getYear()), EduTalentPool::getYear, vo.getYear());
        queryWrapper.lambda().like(!ObjectUtils.isEmpty(vo.getTalentFullName()), EduTalentPool::getTalentFullName, vo.getTalentFullName());
        queryWrapper.lambda().eq(!ObjectUtils.isEmpty(vo.getTalentIdcard()), EduTalentPool::getTalentIdcard, vo.getTalentIdcard());
        queryWrapper.lambda().eq(!ObjectUtils.isEmpty(vo.getTalentLevel()), EduTalentPool::getTalentLevel, vo.getTalentLevel());
        queryWrapper.lambda().eq(!ObjectUtils.isEmpty(vo.getDataSource()), EduTalentPool::getDataSource, vo.getDataSource());
        if (!CollectionUtils.isEmpty(vo.getOrderVOList())) {
            //前端排序字段自动处理，这里面只能根据表里有的字段进行排序，并且只支持单表
            CommonUtil.pageOrder(vo,queryWrapper);
        }else{
            queryWrapper.lambda().orderByDesc(EduTalentPool::getCreateTime, EduTalentPool::getTalentId);
        }
        PageHelper.startPage(vo.getPageNum(),vo.getPageSize());
        List<EduTalentPool> list = eduTalentPoolService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduTalentPool> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduTalentPoolVO> resultList = Convert.toList(EduTalentPoolVO.class, pageInfo.getList());
        // 转义数据字典值
        //dictHelper.valueToName(resultList, Arrays.asList(EduTalentPoolDictEnum.values()));
        // 转义行政区划值
        for(EduTalentPoolVO item:resultList){
            if(StringUtils.isNotBlank(item.getAreaCode())){
                item.setAreaName(dictHelper.getAreaNameByCode(item.getAreaCode()));
            }
        }
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    @Override
    @OpApi(funcCode = "eduTalentPool0002", title = "人才库信息查询详情", funcType = FuncTypeEnum.query,checkPrivilege = BoolEnum.FALSE)
    public EduTalentPoolVO getById(EduTalentPoolKeyVO vo) {
        EduTalentPool entity = eduTalentPoolService.getById(vo.getTalentId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("查询不到详细信息!");
        }
        EduTalentPoolVO result = Convert.convert(EduTalentPoolVO.class, entity);
        // 转义数据字典值
        dictHelper.valueToName(result, Arrays.asList(EduTalentPoolDictEnum.values()));
        // 转义行政区划值
        if (StringUtils.isNotBlank(result.getAreaCode())&&StringUtils.isBlank(result.getAreaName())){
            result.setAreaName(dictHelper.getAreaNameByCode(result.getAreaCode()));
        }
        return result;
    }
    /** 保存前统一校验*/
    @Override
    public void checkSave(EduTalentPoolVO vo) {
        if(StringUtils.isBlank(vo.getAreaCode())){
            vo.setAreaCode(areaCodeHelper.getAreaCode());
        }
        if (StringUtils.isBlank(vo.getTalentFullName())){
            throw new AppException("人才姓名不能为空");
        }
        if (StringUtils.isBlank(vo.getTalentIdcard())){
            throw new AppException("人才证件号码不能为空");
        }
        if (StringUtils.isBlank(vo.getTalentLevel())){
            throw new AppException("人才等级不能为空");
        }
        if(StringUtils.isNotBlank(vo.getAreaCode())){
            vo.setAreaName(dictHelper.getAreaNameByCode(vo.getAreaCode()));
        }
        if (vo.getYear() == null) {
            vo.setYear(eduHelper.thisYear());
        }
        if (StringUtils.isNotBlank(vo.getTalentCardType())){
            vo.setTalentCardType(CardTypeEnum.idcard.getType());
        }
        if (vo.getTalentCardType().equals(CardTypeEnum.idcard.getType())&&StringUtils.isNotBlank(vo.getTalentIdcard())){
            if (!IdcardUtil.isValidCard(vo.getTalentIdcard())){
                throw new AppException("身份证号码格式不正确!");
            }
        }
        if (StringUtils.isBlank(vo.getDataSource())){
            vo.setDataSource("2");//业务录入
        }
        QueryWrapper<EduTalentPool> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EduTalentPool::getTalentIdcard, vo.getTalentIdcard());
        queryWrapper.lambda().eq(EduTalentPool::getYear, vo.getYear())
                .ne(vo.getTalentId()!=null, EduTalentPool::getTalentId, vo.getTalentId());
        if (eduTalentPoolService.count(queryWrapper)>0){
            throw new AppException("该身份证号码已存在!");
        }

    }

    @Override
    @OpApi(funcCode = "eduTalentPool0004", title = "人才库信息新增", funcType = FuncTypeEnum.insert)
    @SaveOplog(
            operationType = "eduTalentPool0004",
            operationName = "人才库信息新增",
            dataType = "talentId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduTalentPoolVO add(EduTalentPoolVO vo) {
        //保存前校验
        checkSave(vo);
        //保存数据
        EduTalentPool entity = Convert.convert(EduTalentPool.class, vo);
        eduTalentPoolService.save(entity);
        //将主键设置回vo使操作日志可以取到
        vo.setTalentId(entity.getTalentId());
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduTalentPool0005", title = "人才库信息修改", funcType = FuncTypeEnum.update)
    @SaveOplog(
            operationType = "eduTalentPool0005",
            operationName = "人才库信息修改",
            dataType = "talentId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduTalentPoolVO edit(EduTalentPoolVO vo) {
        if (ObjectUtils.isEmpty(vo.getTalentId())) {
            throw new AppException("传入需要修改的主键不能为空!");
        }
        EduTalentPool oldEntity = eduTalentPoolService.getById(vo.getTalentId());
        if (ObjectUtils.isEmpty(oldEntity)) {
            throw new AppException("查询不到需要修改的信息!");
        }
        //保存前校验
        checkSave(vo);
        //保存数据
        EduTalentPool entity = Convert.convert(EduTalentPool.class, vo);
        eduTalentPoolService.updateById(entity);
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduTalentPool0006", title = "人才库信息单个删除", funcType = FuncTypeEnum.delete)
    @SaveOplog(
            operationType = "eduTalentPool0006",
            operationName = "人才库信息删除",
            dataType = "talentId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public void del(EduTalentPoolKeyVO vo) {
        if (ObjectUtils.isEmpty(vo.getTalentId())) {
            throw new AppException("传入需要删除的数据主键不能为空!");
        }
        EduTalentPool entity = eduTalentPoolService.getById(vo.getTalentId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("未找到需要删除的信息!");
        }
        eduTalentPoolService.removeById(vo.getTalentId());
    }
    @Override
    @OpApi(funcCode = "eduTalentPool0007", title = "人才库信息批量删除", funcType = FuncTypeEnum.delete)
    @Transactional
    public void delBatch(EduTalentPoolKeyVO vo) {
        if (CollectionUtils.isEmpty(vo.getTalentIdList())) {
            throw new AppException("传入需要删除的数据主键不能为空!");
        }
        eduTalentPoolService.removeByIds(vo.getTalentIdList());
    }

    @Override
    @OpApi(funcCode = "eduTalentPool0008", title = "人才库信息导入模板下载", funcType = FuncTypeEnum.download, checkPrivilege = BoolEnum.FALSE)
    public void downloadModel(ExcelVO vo, HttpServletResponse response) {
        if(StringUtils.isBlank(vo.getModelCode())){
            vo.setModelCode("eduTalentPoolExcel");
        }
        // todo 请核对导出模版中下拉框数据处理是否准确，比如单位选择需要自己单独处理，核对后删除该注释
        Map<String, List<SelectVO>> dictMap = new HashMap<>();
        vo.setDictMap(dictMap);
        excelIntegration.downloadModel(vo, response);
    }

    @Override
    @OpApi(funcCode = "eduTalentPool0009", title = "人才库信息数据导入", funcType = FuncTypeEnum.upload)
    public EduTalentPoolImpFileVO impExcel(EduTalentPoolImpFileVO vo, MultipartFile file) {
        if(StringUtils.isBlank(vo.getModelCode())){
            vo.setModelCode("eduTalentPoolExcel");
        }
        if(file==null){
            throw new AppException("上传文件不能为空");
        }
        EduTalentPoolImpFileVO impFileVO = new EduTalentPoolImpFileVO();
        impFileVO.setCount(0);
        impFileVO.setSuccessCount(0);
        impFileVO.setErrorCount(0);
        //获取excel模版情况
        ExcelVO excelVO = Convert.convert(ExcelVO.class, vo);
        ExcelModelVO excelModelVO = excelIntegration.getModel(excelVO);
        List<EduTalentPoolVO> list=new ArrayList<>();
        InputStream in = null;
        try {
            in = file.getInputStream();
            list = excelCommonHelper.readExcel(excelModelVO, in,EduTalentPoolVO.class, true);
        }catch (IOException e){
            throw new AppException("导入异常：" + e.getMessage());
        }finally {
            if (in != null) {
                try {
                    in.close();
                }catch (Exception e){
                    log.error("关闭流异常",e);
                }
            }
        }
        if (CollectionUtils.isEmpty(list)) {
            throw new AppException("导入数据不能为空");
        }
        impFileVO.setCount(list.size());
        //存放本次导入校验通过的数据
        List<EduTalentPoolVO> successList = new ArrayList<>();

        //存放本次导入校验不通过的数据
        List<EduTalentPoolVO> errorList = new ArrayList<>();
        for(EduTalentPoolVO item:list){
            //数据字典中文转key
            dictHelper.nameToValue(item, Arrays.asList(EduTalentPoolDictEnum.values()));
            boolean successFlag=true;
            String errorMsg="";
            //必填校验
            if (ObjectUtils.isEmpty(item.getYear())) {
                successFlag=false;
                if(StringUtils.isNotBlank(errorMsg)){
                    errorMsg=errorMsg+";"+"招生年度不能为空";
                }else{
                    errorMsg="招生年度不能为空";
                }
            }
            if (ObjectUtils.isEmpty(item.getTalentFullName())) {
                successFlag=false;
                if(StringUtils.isNotBlank(errorMsg)){
                    errorMsg=errorMsg+";"+"人才姓名不能为空";
                }else{
                    errorMsg="人才姓名不能为空";
                }
            }
            if (ObjectUtils.isEmpty(item.getTalentCardType())) {
                successFlag=false;
                if(StringUtils.isNotBlank(errorMsg)){
                    errorMsg=errorMsg+";"+"人才证件类型不能为空";
                }else{
                    errorMsg="人才证件类型不能为空";
                }
            }
            if (ObjectUtils.isEmpty(item.getTalentIdcard())) {
                successFlag=false;
                if(StringUtils.isNotBlank(errorMsg)){
                    errorMsg=errorMsg+";"+"人才证件号码不能为空";
                }else{
                    errorMsg="人才证件号码不能为空";
                }
            }
            // todo 添加其他校验，比如字段格式身份证、手机号码等，核对后删除该注释

            if(successFlag){
                //todo 校验通过后 判断数据是否存在，请根据实际情况判断数据存在是否可以覆盖，核对后删除该注释
                boolean existFlag=false;

                TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
                transactionTemplate.execute(status -> {
                    try {
                        if(!existFlag){
                            this.add(item);
                        }else{
                            this.edit(item);
                        }
                        successList.add(item);
                        impFileVO.setSuccessCount(impFileVO.getSuccessCount()+1);
                        return true;
                    } catch (AppException e){
                        status.setRollbackOnly();
                        item.setImpErrorMsg(e.getMessage());
                        errorList.add(item);
                        impFileVO.setErrorCount(impFileVO.getErrorCount()+1);
                    }catch (Exception e) {
                        status.setRollbackOnly();
                        String msg=e.getMessage();
                        if(StringUtils.isNotBlank(msg)){
                            if(msg.length()>200){
                                msg=msg.substring(0,200);
                            }
                        }
                        item.setImpErrorMsg(msg);
                        errorList.add(item);
                        impFileVO.setErrorCount(impFileVO.getErrorCount()+1);
                    }
                    return false;
                });
            }else{
                item.setImpErrorMsg(errorMsg);
                errorList.add(item);
                impFileVO.setErrorCount(impFileVO.getErrorCount()+1);
            }
            if(successFlag){
                successList.add(item);
                impFileVO.setSuccessCount(impFileVO.getSuccessCount()+1);
            }else{
                item.setImpErrorMsg(errorMsg);
                errorList.add(item);
                impFileVO.setErrorCount(impFileVO.getErrorCount()+1);
            }
        }
        impFileVO.setSuccessList(successList);
        impFileVO.setErrorList(errorList);
        return impFileVO;
    }
    @Override
    @OpApi(funcCode = "eduTalentPool0010", title = "人才库信息数据导出", funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void expExcel(EduTalentPoolQueryVO vo, HttpServletResponse response) {
        ExcelVO excelVO = new ExcelVO();
        excelVO.setModelCode("eduTalentPoolExcelExp");
        ExcelModelVO excelModelVO = excelIntegration.getModel(excelVO);
        String destFilePath = this.tempPath + "/" + IdUtil.fastSimpleUUID() + "." + excelModelVO.getExcelType();
        int pageNum = 1;
        this.setData(excelModelVO, null, destFilePath, vo, pageNum,"eduTalentPoolExcelExp");

        String fileName = "人才库信息" + DateUtil.today() + "." + (StringUtils.isBlank(excelModelVO.getExcelType()) ? "xls" : excelModelVO.getExcelType());
        File file = FileUtil.file(destFilePath);
        BufferedInputStream in = null;
        try {
            in = FileUtil.getInputStream(file);
            ServletUtil.write(response, in, "application/octet-stream;charset=utf-8", fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            FileUtil.del(destFilePath);
        }
    }
    //分页获取需要下载的excel数据
    private void setData(ExcelModelVO excelModelVO, ExcelWriter excelWriter, String destFilePath, EduTalentPoolQueryVO vo, int pageNum,String ModelCode) {
        vo.setPageNum(pageNum);
        vo.setPageSize(500);
        boolean closeFlag = false;
        PageInfo<EduTalentPoolVO> pageInfo = null;
        try {
            pageInfo = getList(vo);
            String total = String.valueOf(pageInfo.getTotal());
            List<Map<String, Object>> list = new ArrayList<>();
            if (!CollectionUtils.isEmpty(pageInfo.getList())) {
                for (EduTalentPoolVO itemVO : pageInfo.getList()) {
                    list.add(BeanUtil.beanToMap(itemVO, false, true));
                }
            }
            if (pageNum == 1) {
                if (excelWriter == null) {
                    excelWriter = excelCommonHelper.createExcelWriter(excelModelVO, destFilePath, Integer.parseInt(total));
                }
                excelCommonHelper.writeMap(excelWriter, list);
            } else {
                excelCommonHelper.writeMap(excelWriter, list);
            }
            if (pageInfo.isHasNextPage()) {
                pageNum = pageNum + 1;
                this.setData(excelModelVO, excelWriter, destFilePath, vo, pageNum,ModelCode);
            } else {
                closeFlag = true;
            }
        } catch (AppException appEx) {
            throw appEx;
        } catch (Exception e) {
            throw new AppException("调用自定义写入服务异常:" + e.getMessage());
        } finally {
            if (closeFlag && excelWriter != null) {
                excelWriter.close();
            }
        }
    }
}
